package com.agadmin.config;

import com.agadmin.common.JWTUtil;
import com.agadmin.response.BaseResponse;
import com.alibaba.fastjson2.JSON;
import jakarta.annotation.Resource;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Slf4j
@Configuration
public class SecurityConfiguration {
    @Resource
    JWTAuthorizeFilter filter;

    @Resource
    RedisTemplate<String,Object> redisTemplate;

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {

        return http.
                authorizeHttpRequests(conf -> conf.
                        requestMatchers("/api/auth/**","/api/check/**").permitAll()
                        .anyRequest().authenticated()
                )
                .formLogin(conf -> conf
                        .usernameParameter("userName")
                        .loginProcessingUrl("/api/auth/login")
                        .successHandler(this::onAuthenticationSuccess)
                        .failureHandler(this::onAuthenticationFailure)

                ).logout(conf -> conf
                        .logoutUrl("/api/auth/logout")
                        .logoutSuccessHandler(this::onLogoutSuccess)

                )
                .exceptionHandling(conf ->
                        conf.authenticationEntryPoint(this::commence)
                )

                .csrf(AbstractHttpConfigurer::disable)
                .sessionManagement(conf -> conf
                        .sessionCreationPolicy(SessionCreationPolicy.STATELESS))//禁用session

                .addFilterBefore(filter, UsernamePasswordAuthenticationFilter.class)
                .build();

    }

//    when login succ
    public void onAuthenticationSuccess(HttpServletRequest request,
                                        HttpServletResponse response,
                                        Authentication authentication)
            throws IOException, ServletException {
        CustomUser user = (CustomUser) authentication.getPrincipal();

        log.info(user.getSysUser().toString());
        log.info(user.getSysUser().getId().toString());

        response.setContentType("application/json;charset=utf-8");

        String token = JWTUtil.createToken(user, user.getSysUser().getId().toString(),
                user.getUsername());
        BaseResponse res = new BaseResponse();
        res.setData(token);
        res.setCode(200);
        Map<String,String> map=new HashMap();
        map.put("token",token);
        response.setHeader("token",token);
        res.setMsg("login successful");
        res.setData(map);

        redisTemplate.opsForValue().set(user.getSysUser().getId(),token,1, TimeUnit.HOURS);
        
        response.getWriter().write(JSON.toJSONString(res));
    }

    public void onAuthenticationFailure(HttpServletRequest request,
                                        HttpServletResponse response,
                                        AuthenticationException exception)
            throws IOException, ServletException {
        BaseResponse res=new BaseResponse();
        res.setError(exception.getMessage());
        res.setCode(403);
        response.getWriter().write(JSON.toJSONString(res));
    }

    public void onLogoutSuccess(HttpServletRequest request,
                                HttpServletResponse response,
                                Authentication authentication)
            throws IOException, ServletException {

    }

    //没有权限
    public void commence(HttpServletRequest request, HttpServletResponse response,
                         AuthenticationException authException)
            throws IOException, ServletException {

        log.error(authException.getMessage());
        BaseResponse res=new BaseResponse();
        res.setError(authException.getMessage());
        res.setCode(403);

        response.getWriter().write(JSON.toJSONString(res));

    }

}
